package com.dmyang.websocket;

import com.dmyang.entity.Message;
import com.dmyang.vo.UserVo;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.SynchronousQueue;

/**
 * Socket处理器
 */
@Component
public class MyWebSocketHandler implements WebSocketHandler {
	//用于保存HttpSession与WebSocketSession的映射关系
	public static final Map<String, WebSocketSession> userSocketSessionMap;
	public static final ArrayBlockingQueue patientQueue;
	public static final ArrayBlockingQueue doctorQueue;
	public static final Map<String,List<UserVo>> relation_doc;
	public static final Map<String,List<UserVo>> relation_pat;


	static {
		userSocketSessionMap = new ConcurrentHashMap<String, WebSocketSession>();
		patientQueue = new ArrayBlockingQueue(100,true);
		doctorQueue = new ArrayBlockingQueue(100,true);
		relation_doc = new ConcurrentHashMap<>();
		relation_pat = new ConcurrentHashMap<>();
	}

	
	/**
	 * 建立连接后,把登录用户的id写入WebSocketSession
	 */
	public void afterConnectionEstablished(WebSocketSession socketSession)
			throws Exception {
		System.out.println("websessionId="+socketSession.getId());
		String pk = (String)socketSession.getAttributes().get("pk");
		String role = (String) socketSession.getAttributes().get("role");
		//创建chatWith的List，以后使用
		List chatWith = new ArrayList();
		socketSession.getAttributes().put("chatWith",chatWith);

		if (userSocketSessionMap.get(pk)==null){
			userSocketSessionMap.put(pk,socketSession);
			Message msg = new Message();
			msg.setFrom("-1");//0表示上线消息
			String username= (String) socketSession.getAttributes().get("name");
			msg.setText(username);
			this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
		}
	}

	/**
	 * 消息处理，在客户端通过Websocket API发送的消息会经过这里，然后进行相应的处理
	 */
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
		System.out.println("收到客户端发送的消息");
		if(message.getPayloadLength()==0)
			return;
		Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
		msg.setDate(new Date());
		if (msg.getTo().equals("89124053")){
			//群发消息
			broadcast_doc( msg );
		}else {
			sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
		}
	}

	/**
	 * 消息传输错误处理
	 */
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {
		System.out.println("消息传输错误");
		if (session.isOpen()) {
			session.close();
		}
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
		// 移除当前抛出异常用户的Socket会话
		while (it.hasNext()) {
			Entry<String, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				userSocketSessionMap.remove(entry.getKey());
				System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
				String username= (String) session.getAttributes().get("name");
				Message msg = new Message();
				msg.setFrom("-2");
				msg.setText(username);
				this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
				break;
			}
		}
	}

	/**
	 * 关闭连接后
	 */
	public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
		System.out.println("Websocket:" + session.getId() + "已经关闭");
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
		// 移除当前用户的Socket会话
		while (it.hasNext()) {
			Entry<String, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				userSocketSessionMap.remove(entry.getKey());
				System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
				String username= (String) session.getAttributes().get("name");
				Message msg = new Message();
				msg.setFrom("-2");//下线消息，用-2表示
				msg.setText(username);
				this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
				break;
			}
		}
	}

	public boolean supportsPartialMessages() {
		return false;
	}

	/**
	 * 给所有在线用户发送消息
	 * @param message
	 * @throws IOException
	 */
	public void broadcast(final TextMessage message) throws IOException {
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();

		//多线程群发
		while (it.hasNext()) {

			final Entry<String, WebSocketSession> entry = it.next();

			if (entry.getValue().isOpen()) {
				// entry.getValue().sendMessage(message);
				new Thread(new Runnable() {

					public void run() {
						try {
							if (entry.getValue().isOpen()) {
								entry.getValue().sendMessage(message);
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

				}).start();
			}

		}
	}

	/**
	 * 给所有在线医生发送消息
	 * @param message
	 * @throws IOException
	 */
	public void broadcast_doc(final Message message) throws IOException {

		final TextMessage textMessage = new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(message));

		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();

		//多线程群发
		while (it.hasNext()) {

			final Entry<String, WebSocketSession> entry = it.next();
			//排除自己，给所有的在线医生发送消息
			if ( entry.getValue().isOpen() && entry.getValue().getAttributes().get("role").equals("doctor") && !entry.getValue().getAttributes().get("pk").equals(message.from) ) {
				// entry.getValue().sendMessage(message);
				new Thread(new Runnable() {

					public void run() {
						try {
							if (entry.getValue().isOpen()) {
								entry.getValue().sendMessage(textMessage);
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

				}).start();
			}

		}
	}


	/**
	 * 给某个用户发送消息
	 * 
	 * @param pk 主键
	 * @param message
	 * @throws IOException
	 */
	public void sendMessageToUser(String pk, TextMessage message) throws IOException {
		WebSocketSession session = userSocketSessionMap.get(pk);
		if (session != null && session.isOpen()) {
			session.sendMessage(message);
			System.out.println("发送成功");
		}
	}

}
